// import { useStorage } from '@vueuse/core'
import artTemplate from "art-template"
import dot from "dot"
import dayjs from "dayjs"
import _ from "lodash"

/**
 * 状态值
 */
const commonFunction =  `


<% 
//--------------------------------自定义函数 开始-------------------------------- 
// Ark模板: https://goofychris.github.io/art-template/zh-cn/docs/index.html

// 已引入的常用函数: dayjs, lodash(_), 可直接使用，文档参考如下
// 日期处理: dayjs   https://dayjs.fenxianglu.cn/category
// 常用函数：lodash  https://www.lodashjs.com

// 转驼峰
function camel(str) {
  return str?.replace(/_(\\w)/g, (_, p1) => p1.toUpperCase())
}

// 帕斯卡命名（大驼峰）
function pascal(str) {
  const newStr = camel(str)
  return newStr ? newStr.charAt(0).toUpperCase() + newStr.slice(1) : newStr;
}

// 下划线
function snake(str) {
  return str?.replace(/([A-Z])/g, '_$1').toLowerCase();
}

/* 类型映射 */
function typeMapping(columnType, lang) {
  // 为了能够将函数写到模板的下面，定义在函数里面了
  const typeMappingData = [
    {id: 'sys01', name: '字符串', code: 'STRING'  , color: '#409eff', enabled: true, mysql: 'VARCHAR' , oracle: 'VARCHAR2', postgres: 'VARCHAR'  , java: 'String' , rust: 'String'         , go: 'string'     , sourceTypes: 'STRING, VARCHAR, VARCHAR2, CHARACTER VARYING, CHAR, CHARACTER'},
    {id: 'sys02', name: '整数'  , code: 'INT'     , color: '#67c23a', enabled: true, mysql: 'INT'     , oracle: 'INT'     , postgres: 'INT'      , java: 'Integer', rust: 'i32'            , go: '*int'       , sourceTypes: 'INT, INTEGER, SERIAL'},
    {id: 'sys03', name: '小数'  , code: 'DECIMAL' , color: '#e6a23c', enabled: true, mysql: 'DECIMAL' , oracle: 'DECIMAL' , postgres: 'DECIMAL'  , java: 'Double' , rust: 'f64'            , go: '*float64'   , sourceTypes: 'DECIMAL, NUMERIC, REAL, DOUBLE'},
    {id: 'sys04', name: '日期'  , code: 'DATETIME', color: '#909399', enabled: true, mysql: 'DATETIME', oracle: 'DATE'    , postgres: 'TIMESTAMP', java: 'Date'   , rust: 'DateTime<Local>', go: '*time.Time' , sourceTypes: 'DATE, DATETIME, TIMESTAMP'},
    {id: 'sys05', name: '大文本', code: 'TEXT'    , color: '#f56c6c', enabled: true, mysql: 'TEXT'    , oracle: 'CLOB'    , postgres: 'TEXT'     , java: 'String' , rust: 'String'         , go: 'string'     , sourceTypes: 'TEXT, CLOB'},
    {id: 'sys06', name: '二进制', code: 'BLOB'    , color: '#f56c6c', enabled: true, mysql: 'BLOB'    , oracle: 'BLOB'    , postgres: 'BYTEA'    , java: 'byte[]' , rust: 'Vec<u8>'        , go: '[]byte'     , sourceTypes: 'BLOB, BYTEA'},
  ]

  // varchar(20) ==> VARCHAR
  const simpleType = columnType?.split('(')[0]?.toUpperCase()
  for (let type of typeMappingData) {
    const arr = type.sourceTypes.split(',').map(t => t.trim())
    if (arr.includes(simpleType)) {
      return type[lang]
    }
  }
  return columnType
}
//--------------------------------自定义函数 结束-------------------------------- 
%>`

export const state =  reactive({
  json: `{
    "tableComment": "用户表",
    "tableName": "sys_user",
    "columns": [
      {
        "columnComment": "主键",
        "columnName": "id",
        "columnType": "varchar(64)",
        "isPrimary": true,
        "isAutoIncrement": false,
        "isNonNull": true,
        "columnDefault": null
      },
      {
        "columnComment": "账号",
        "columnName": "username",
        "columnType": "varchar(64)",
        "isPrimary": false,
        "isAutoIncrement": false,
        "isNonNull": true,
        "columnDefault": null
      },
      {
        "columnComment": "密码",
        "columnName": "password",
        "columnType": "varchar(256)",
        "isPrimary": false,
        "isAutoIncrement": false,
        "isNonNull": true,
        "columnDefault": null
      },
      {
        "columnComment": "姓名",
        "columnName": "name",
        "columnType": "varchar(64)",
        "isPrimary": false,
        "isAutoIncrement": false,
        "isNonNull": false,
        "columnDefault": null
      },
      {
        "columnComment": "手机号",
        "columnName": "phone",
        "columnType": "varchar(64)",
        "isPrimary": null,
        "isAutoIncrement": false,
        "isNonNull": false,
        "columnDefault": null
      },
      {
        "columnComment": "邮箱",
        "columnName": "email",
        "columnType": "varchar(64)",
        "isPrimary": null,
        "isAutoIncrement": false,
        "isNonNull": false,
        "columnDefault": null
      },
      {
        "columnComment": "登录错误次数",
        "columnName": "err_count",
        "columnType": "int",
        "isPrimary": false,
        "isAutoIncrement": false,
        "isNonNull": false,
        "columnDefault": null
      },
      {
        "columnComment": "身价资产(元)",
        "columnName": "personal_value",
        "columnType": "decimal(18,2)",
        "isPrimary": false,
        "isAutoIncrement": false,
        "isNonNull": false,
        "columnDefault": null
      },
      {
        "columnComment": "状态(0-正常 1-停用)",
        "columnName": "status",
        "columnType": "varchar(1)",
        "isPrimary": false,
        "isAutoIncrement": false,
        "isNonNull": true,
        "columnDefault": "'0'"
      },
      {
        "columnComment": "创建人",
        "columnName": "create_by",
        "columnType": "varchar(64)",
        "isPrimary": false,
        "isAutoIncrement": false,
        "isNonNull": false,
        "columnDefault": null
      },
      {
        "columnComment": "创建时间",
        "columnName": "create_at",
        "columnType": "timestamp",
        "isPrimary": false,
        "isAutoIncrement": false,
        "isNonNull": false,
        "columnDefault": null
      },
      {
        "columnComment": "修改人",
        "columnName": "update_by",
        "columnType": "varchar(64)",
        "isPrimary": false,
        "isAutoIncrement": false,
        "isNonNull": false,
        "columnDefault": null
      },
      {
        "columnComment": "修改时间",
        "columnName": "update_at",
        "columnType": "timestamp",
        "isPrimary": false,
        "isAutoIncrement": false,
        "isNonNull": false,
        "columnDefault": null
      },
      {
        "columnComment": "删除标志(0-未删除 1-已删除)",
        "columnName": "delete_flag",
        "columnType": "varchar(1)",
        "isPrimary": false,
        "isAutoIncrement": false,
        "isNonNull": true,
        "columnDefault": "'0'"
      }
    ]
  }`.trim(),
  modules: ['JavaScript引擎', 'Ark模板'],
  module: 'JavaScript引擎',
  jsTmpl: `
/* javascript引擎，json数据绑定为this, return返回内容输出到渲染区域 */
/* 原理: new Function(code).bind(jsonObject).call()*/
return this.columns.map(c => c.columnName)
    `.trim(),
  dialog: false,
  lang: 'java',
  tmpl: {
    java: `
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fofund.ark.common.annotation.Keyword;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.hibernate.validator.constraints.Length;

import java.util.List;
<%
/* 通用字段的特殊处理 */
const modelName = pascal(tableName.split('_')[1])  // 去掉sys_前缀
const createColumns = ['create_by','create_at']
const updateColumns = ['update_by','update_at'] 
const deleteFlag = 'delete_flag'
%>
/**
 * {{_.trimEnd(tableComment, '表')}}
 *
 * @author metaman {{dayjs().format('YYYY-MM-DD')}}
 */
@Data
@TableName("{{tableName}}") @Schema(description = "{{_.trimEnd(tableComment, '表')}}")
public class {{modelName}} {
   {{each columns c}}
    @Schema(description = "{{c.columnComment}}"){{if c.isPrimary}}
    @TableId(type = IdType.ASSIGN_ID){{/if}}{{if createColumns.indexOf(_.toLower(c.columnName)) > 0}}
    @TableField(fill = FieldFill.INSERT, updateStrategy = FieldStrategy.NEVER){{/if}}{{if updateColumns.indexOf(_.toLower(c.columnName)) > 0}}
    @TableField(fill = FieldFill.UPDATE, insertStrategy = FieldStrategy.NEVER){{/if}}{{if deleteFlag === c.columnName}}
    @TableLogic  @JsonIgnore{{/if}}
    private {{typeMapping(c.columnType,'java')}} {{camel(c.columnName)}};
   {{/each}}
}

${commonFunction}
  `.trim(),
    rust: `
use chrono::{DateTime, Local};
use serde::{Deserialize, Serialize};
<%
const modelName = pascal(tableName.split('_')[1])  // 去掉sys_前缀
%>
/// {{_.trimEnd(tableComment, '表')}}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct {{modelName}} {
    {{each columns c}}
    /// {{c.columnComment}}
    pub {{camel(c.columnName)}}: {{if c.isNonNull}}{{typeMapping(c.columnType,'rust')}}{{else}}Option<{{typeMapping(c.columnType,'rust')}}>{{/if}},
    {{/each}}
}

${commonFunction}
    `.trim(),
    go: `
package models
<%
// 去掉sys_前缀
const modelName = pascal(tableName.split('_')[1])  

// 最大字段长度和类型长度，用于对齐
const maxFieldLength = columns.map(c => pascal(c.columnName).length).reduce( (p,n) => p > n ? p : n)
const maxTypeLength  = columns.map(c => typeMapping(c.columnType, 'go').length).reduce( (p,n) => p > n ? p : n)
%>
type {{modelName}} struct { {{each columns c}}
    {{_.padEnd(pascal(c.columnName), maxFieldLength)}} {{_.padEnd(typeMapping(c.columnType,'go'),maxTypeLength)}} \`json:"{{camel(c.columnName)}}"\`{{_.padEnd('', maxFieldLength - pascal(c.columnName).length) }} // {{c.columnComment}} {{/each}}
}

${commonFunction}
    `.trim(),
  }
})

/**
 * 多模板渲染
 */
export function render(name, source, data) {
  try {
    switch (name) {
      case "art"     : return artTemplate.render(source, data, {imports: {dayjs, _}, debug: true})
      case "lodash"  : return _.template(source, {imports: {dayjs, }})(data)
      case "dot"     : return dot.template(source)({dayjs, _, ...data})
      default        : return `${name} 模板引擎暂不支持`
    }
  } catch (e) {
    return `${name}模板报错: ${e}`
  }
}

/**
 * js引擎执行
 */
export function execute(obj, code) {
  try {
    const userFunc = new Function(code)
    return JSON.stringify(userFunc.bind(obj).call(), null, 2)
  } catch (e) {
    return `js引擎报错: ${e}`
  }
}